#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>

uint16_t ReadADC(uint8_t ADCchannel)
{
	// select ADC channel with safety mask
	ADMUX = (ADMUX & 0xF0) | (ADCchannel & 0x0F);
	// single conversion mode
	ADCSRA |= (1<<ADSC);
	// wait until ADC conversion is complete
	while(ADCSRA & (1<<ADSC));
	return ADC;
}


int main()
{
	float low_adc, high_adc;
	int pot;
	
	DDRB = 0x02;	// set PB1/OC1A as output
	DDRC = 0x00;	// set Port C as input
	DDRD = 0xFF;	// set Port D as output
	PORTC = 0x00;	// clear Port C
	
	TCCR1A = 0xA2;	// COM1A/B = 10, clear OC1A/B on compare match
	TCCR1B = 0x1A;	// WGM = 1110, fast PWM, TOP = ICR1, prescaler = 8
	
	ICR1 = 20000;	// setup ICR1 (for servo)
	
	ADMUX = 0x80;	// AVCC with external capacitor at AREF pin
	ADCSRA = 0x87;	// ADC enable, prescaler = 128, clk = F_CPU/128 = 62500

	while(1)
	{
		// STEPPER MOTOR:
		pot=ReadADC(3)/6;	// read and scale the ADC value input from a potentiometer
		
		// the following code uses the potentiometer value 
		// to set the delay and thus the speed for the stepper motor:
		PORTD = 0x66;
		for(int i=0;i<pot+20;i++)
		_delay_ms(1);
		PORTD = 0x33;
		for(int i=0;i<pot+20;i++)
		_delay_ms(1);
		PORTD = 0x99;
		for(int i=0;i<pot+20;i++)
		_delay_ms(1);
		PORTD = 0xCC;
		for(int i=0;i<pot+20;i++)
		_delay_ms(1);
		
		
		// SERVO MOTOR:		
		// save ADC values in float variables in order to retain 
		// greater precision in later conversion
		low_adc = ADCL;
		high_adc = ADCH;

		// This is the conversion to set the PWM for the correct servo position:
		high_adc = high_adc*256.0;
		high_adc = high_adc+low_adc;
		high_adc = (1800.0/1024.0)*high_adc;

		OCR1A = 500+high_adc; // send 500 + high to Output Compare Register
	}
	return 0;
}
